package com.woniu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.entity.*;
import com.woniu.mapper.*;
import com.woniu.service.FootprintService;
import com.woniu.service.vo.TestPageVo;
import com.woniu.service.vo.TestVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author D
 * @since 2023-03-27 08:24:57
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class FootprintServiceImpl extends ServiceImpl<FootprintMapper, Footprint> implements FootprintService {
    @Autowired
    private FootprintMapper footprintMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TestOutsideMapper testOutsideMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private TestTypeMapper testTypeMapper;
    @Autowired
    private TestDetailMapper testDetailMapper;


    /**
     * 保存用户靶场历史记录,如果已经存在则更新时间,否则插入新的记录并更新测试次数+1
     *
     * @param testCode 靶场编号
     * @param userCode 用户名
     * @return 返回操作结果，-1 和 0 表示操作失败，其他表示操作成功
     */
    @Override
    public Integer saveHistory(Long testCode, Long userCode) {
        //查询是否存在记录
        QueryWrapper<Footprint> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_code", userCode);
        queryWrapper.eq("test_code", testCode);
        Footprint footprint = footprintMapper.selectOne(queryWrapper);
        TestOutside testOutside = testOutsideMapper.selectById(testCode);
        int result = -1;
        if (footprint == null) {
            //不存在记录则插入新的记录
            Footprint footprint1 = new Footprint();
            footprint1.setTestCode(testCode);
            footprint1.setUserCode(userCode);
            footprint1.setUpdateTime(new Date());
            result = footprintMapper.insert(footprint1);
            testOutside.setUserdNumbers(testOutside.getUserdNumbers() + 1);
            testOutsideMapper.updateById(testOutside);
        } else {
            //存在记录则更新时间
            footprint.setUpdateTime(new Date());
            result = footprintMapper.updateById(footprint);
            Set<String> keys = redisTemplate.keys(userCode + "*");
            if (keys != null) {
                redisTemplate.delete(keys);
            }
        }
        return result;
    }
    /**
     * 分页查询用户足迹列表
     *
     * @param userCode    用户编码
     * @param currentPage 当前页码
     * @param pageSize    每页大小
     * @return 靶场信息分页对象
     */
    @Override
    public TestPageVo<TestVo> pageFootprint(Long userCode, Integer currentPage, Integer pageSize) {
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        TestPageVo<TestVo> footprintRedis = (TestPageVo<TestVo>) ops.get(userCode + "Footprint" + currentPage);
        //先查redis,不为空直接返回
        if (footprintRedis != null) {
            return footprintRedis;
        }
        //redis为空时执行以下代码
        QueryWrapper<Footprint> footprintQueryWrapper = new QueryWrapper<>();
        footprintQueryWrapper.eq("user_code", userCode);
        Page page = new Page(currentPage, pageSize);
        Page<Footprint> footprints = footprintMapper.selectPage(page, footprintQueryWrapper);
        List<TestVo> footprintVos = footprints.getRecords().stream().map(f -> {
            TestOutside testOutside = testOutsideMapper.selectById(f.getTestCode());
            TestDetail testDetail = testDetailMapper.selectById(f.getTestCode());
            TestType testType = testTypeMapper.selectById(testDetail.getTestTypeId());
            return new TestVo().testInfo(testOutside, testType);
        }).collect(Collectors.toList());
        TestPageVo<TestVo> testPageVo = new TestPageVo(footprints.getPages(), footprints.getCurrent(), footprints.getSize(), footprints.getTotal(), footprintVos);

        //查出的数据存到redis里
        ops.set(userCode + "Footprint" + currentPage, testPageVo, 7, TimeUnit.DAYS);

        return testPageVo;
    }
}
